﻿/*
--------------------------------------
File: DTUtils.cs
Project: Themaopdracht 7
Author: Roel Blaauwgeers

Description:
Utilities for the DecisionTree.
--------------------------------------
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace THO7_Team8
{
    public class DTUtils
    {
        public static void checkImageAndCalculateCorrect(Bitmap bmp, Bitmap bwbmp, string newFileName, DecisionTree tree)
        {

            int patch_dimension = 5;

            //Get the HSV-values from the test image
            HSV[,] hsvColors = DTUtils.BitmapToArray(bmp);

            double correct = 0;
            double foregroundpx = 0;

            //For all pixels 
            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width; x++)
                {
                    //Check if pixel is a smurfpixel
                    if (!tree.isForegroundPixel(DTUtils.getFeatures(x, y, bmp.Width, bmp.Height, hsvColors, patch_dimension)))
                    {
                        if (bwbmp.GetPixel(x, y).GetBrightness() == 1)
                        {
                            foregroundpx++;
                        }
                        //If not make it black
                        bmp.SetPixel(x, y, Color.Black);
                    }
                    else
                    {
                        if (bwbmp.GetPixel(x, y).GetBrightness() == 1)
                        {
                            correct++;
                            foregroundpx++;
                        }
                    }
                }
            }

            Console.WriteLine(correct);
            Console.WriteLine(foregroundpx);

            Console.WriteLine("Correctness: " + ((correct / foregroundpx) * 100d) + "%");

            //Save the testimage
            bmp.Save(newFileName);
        }

        public static HSV[,] BitmapToArray(Bitmap bmp)
        {
            HSV[,] hsvColors = new HSV[bmp.Width, bmp.Height];

            
            BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);

            unsafe
            {
                byte* imgPtr = (byte*)(data.Scan0);
                byte red, green, blue;
                for (int y = 0; y < data.Height; y++)
                {
                    for (int x = 0; x < data.Width; x++)
                    {
                        blue = imgPtr[0];
                        green = imgPtr[1];
                        red = imgPtr[2];

                        hsvColors[x, y] = new HSV(red, green, blue);

                        imgPtr += 3;
                    }
                    imgPtr += data.Stride - data.Width * 3;
                }
            }

            bmp.UnlockBits(data);

            return hsvColors;
        }

        public static double[] getFeatures(int x, int y, int x_border, int y_border, HSV[,] hsvColors, int patch_dimension)
        {
            //Bin arrays
            int[] hbin = new int[10];
            int[] sbin = new int[10];
            int[] vbin = new int[10];

            //For all patchpixels
            for (int py = y - patch_dimension; py < (y + patch_dimension); py++)
            {
                for (int px = x - patch_dimension; px < (x + patch_dimension); px++)
                {
                    //If not outside borders
                    if (px >= 0 && py >= 0 && px < x_border && py < y_border)
                    {
                        //Add to histogram
                        hbin[(int)((hsvColors[px, py].getHue() * 9f) / 360f)]++;
                        sbin[(int)(hsvColors[px, py].getSaturation() * 9f)]++;
                        vbin[(int)(hsvColors[px, py].getValue() * 9f)]++;
                    }
                }
            }

            //Normalize histogram and put it all together in a double-array
            double[] attributes = new double[30];

            //For all features
            for (int i = 0; i < 30; i++)
            {
                //If H
                if (i < 10)
                {
                    attributes[i] = hbin[i] / (Math.Pow((patch_dimension * 2 + 1), 2)); //Hue
                }
                //If S
                else if (i > 9 && i < 20)
                {
                    attributes[i] = sbin[i - 10] / (Math.Pow((patch_dimension * 2 + 1), 2)); //Saturation
                }
                //If V
                else if (i > 19)
                {
                    attributes[i] = vbin[i - 20] / (Math.Pow((patch_dimension * 2 + 1), 2)); //Value
                }
            }

            return attributes;
        }
    }
}
